package com.solidario.accesodatos;

import java.util.List;

import javax.persistence.EntityManager;

/**
 * Clase con los metodos basicos para la persistencia de una entidad JPA
 * 
 * 
 * @param <T>
 */
public abstract class AccesoDatos<T> {
	/**
	 * Entidad pasada como parametro
	 */
	private Class<T> entityClass;

	/**
	 * Constructor de la clase, con el parametro de entidad
	 * 
	 * @param entityClass
	 */
	public AccesoDatos(Class<T> entityClass) {
		this.entityClass = entityClass;
	}

	/**
	 * Retorna el EntityManager de la entidad
	 * 
	 * @return
	 */
	protected abstract EntityManager getEntityManager();

	/**
	 * Crea o persiste la entidad
	 * 
	 * @param entity
	 */
	public void crear(T entity) {
		getEntityManager().persist(entity);
	}

	/**
	 * edita la entidad
	 * 
	 * @param entity
	 */
	public void modificar(T entity) {
		getEntityManager().merge(entity);
	}

	/**
	 * elimina la entidad
	 * 
	 * @param entity
	 */
	public void eliminar(T entity) {
		getEntityManager().remove(getEntityManager().merge(entity));
	}

	/**
	 * Busca la entidad por si Id
	 * 
	 * @param id
	 * @return
	 */
	public T buscar(Object id) {
		return getEntityManager().find(entityClass, id);
	}

	/**
	 * Retorna una lista con todas las entidades T
	 * 
	 * @return
	 */
	public List<T> buscarTodos() {
		javax.persistence.criteria.CriteriaQuery cq = getEntityManager()
				.getCriteriaBuilder().createQuery();
		cq.select(cq.from(entityClass));
		return getEntityManager().createQuery(cq).getResultList();
	}

	/**
	 * Busca por rangos.
	 * 
	 * @param range
	 * @return
	 */
	public List<T> buscarPorRango(int[] range) {

		javax.persistence.criteria.CriteriaQuery cq = getEntityManager()
				.getCriteriaBuilder().createQuery();
		cq.select(cq.from(entityClass));
		javax.persistence.Query q = getEntityManager().createQuery(cq);
		q.setMaxResults(range[1] - range[0]);
		q.setFirstResult(range[0]);
		return q.getResultList();
	}

	/**
	 * Retrona el tamano de las entidades T
	 * 
	 * @return
	 */
	public int contar() {
		javax.persistence.criteria.CriteriaQuery cq = getEntityManager()
				.getCriteriaBuilder().createQuery();
		javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
		cq.select(getEntityManager().getCriteriaBuilder().count(rt));
		javax.persistence.Query q = getEntityManager().createQuery(cq);
		return ((Long) q.getSingleResult()).intValue();
	}

	public void remover(T entity) {
		getEntityManager().remove(entity);
	}
}
